package com.weidey.blogWeb.service.Impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.weidey.blogWeb.service.ISignService;
import com.weidey.common.core.domain.AjaxResult;
import com.weidey.common.core.redis.RedisCache;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SignServiceImpl implements ISignService {

    @Resource
    private RedisCache redisCache;


    @Override
    public AjaxResult doSign(Long userId, String dateStr) {
        // 获取当前日期对象
        Date nowDate = getNewDate(dateStr);
        int dayOfMonth = DateUtil.dayOfMonth(nowDate) - 1; // 转换为0-based offset

        // 构建Redis Key（按月存储）
        String signKey = buildSignKey(userId, nowDate);
        RedisTemplate<String, Object> redisTemplate = redisCache.redisTemplate;

        // 检查今日是否已签到
        Boolean isSigned = redisTemplate.opsForValue().getBit(signKey, dayOfMonth);
        if (isSigned != null && isSigned) {
            return AjaxResult.warn("今日已签到");
        }

        // 执行签到操作
        redisTemplate.opsForValue().setBit(signKey, dayOfMonth, true);

        // 记录签到月份到集合（优化总次数统计）
        String monthKey = DateUtil.format(nowDate, "yyyy-MM");
        redisTemplate.opsForSet().add("user:sign:months:" + userId, monthKey);

        // 统计结果
        int continuousDays = getContinuousSignDays(userId, new Date());
        int totalSignDays = getTotalSignDays(userId);

        Map<String, Object> result = new HashMap<>();
        result.put("continuous", continuousDays);
        result.put("total", totalSignDays);
        return AjaxResult.success("签到成功", result);
    }

    /**
     * 获取总签到天数（优化版）
     */
    private int getTotalSignDays(Long userId) {

        Set<String> months = redisCache.redisTemplate.opsForSet().members("user:sign:months:" + userId);
        int totalSignDays = 0;

        if (months != null){
            return  totalSignDays;
        }
        // 遍历每个月份，统计签到天数
        for (String month : months) {
            String signKey = "user:sign:" + userId + ":" + month;
            Long count = (Long) redisCache.redisTemplate.execute(
                    (RedisCallback<Long>) conn -> conn.bitCount(signKey.getBytes())
            );
            if (count != null) {
                totalSignDays += count.intValue();
            }
        }
        return  totalSignDays;

    }

    /**
     * 获取连续签到天数
     * @param userId 用户id
     * @param today 当前日期
     * @return 连续签到天数
     */
    private int getContinuousSignDays(Long userId, Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        int continuousDays = 0;
        for (int i = 0; i < 365; i++) { // 最多追溯1年
            String key = buildSignKey(userId, calendar.getTime());
            int dayOffset = DateUtil.dayOfMonth(calendar.getTime()) - 1;

            Boolean isSigned = redisCache.redisTemplate.opsForValue()
                    .getBit(key, dayOffset);

            if (isSigned != null && isSigned) {
                continuousDays++;
                calendar.add(Calendar.DAY_OF_MONTH, -1);
            } else {
                break;
            }
        }
        return continuousDays;
    }

    /**
     * 构建redis key
     * @param userId 用户id
     * @param nowDate 当前日期
     * @return redis key
     */
    private String buildSignKey(Long userId, Date nowDate) {
        return String.format("user:sign:%d:%s", userId,
                DateUtil.format(nowDate, "yyyy-MM"));
    }

    /**
     *  获取日期
     * @param dateStr 日期
     * @return 用户传入的日期 或 当前日期
     */
    private Date getNewDate(String dateStr) {
        return StrUtil.isBlank(dateStr) ? new Date() : DateUtil.parseDate(dateStr);
    }
}
